<?php

namespace App\Kuafu\WaiMai\Command;

use App\Kuafu\Shop\Service\ShopService;
use App\Kuafu\WaiMai\Channel\BaseWaiMai;
use App\Kuafu\WaiMai\Enum\WaiMaiDBEnum;
use App\Kuafu\WaiMai\Model\WaiMaiCallbackLogModel;
use App\Kuafu\WaiMai\Model\WaiMaiOrderDetailModel;
use App\Kuafu\WaiMai\Model\WaiMaiOrderModel;
use App\Kuafu\WaiMai\Service\MtWaiMaiOrderService;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;

class FixData extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'waimai-fixdata';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = '外卖订单自动修复字段';

    /**
     * Create a new command instance.
     *
     * @return void//
     */
    public function __construct()
    {
        parent::__construct();
    }

    private array $errs = [];

    /**
     * Execute the console command
     *
     * @return int
     */
    public function handle()
    {
        // 11.01以后的没有镜像的orderIds
        $emptyOrderIds = [
            108263161320662104,
            108263162699611169,
            108263163088929314,
            108263162521089199,
            130093952224627655,
        ];

        // 1. waimai_orders
        //    美团：packingPrice,discountPrice,otherPrice
        //    饿了么：discountPrice,redPrice, redLists, activityExpenditure, otherPrice

        // 2.waimai_order_details
        // +包装物-行，payPrice, discountPrice, incomes

        // 3. 校验 waimai_orders.originalPrice - originalShippingPrice - packingPrice = sum(waimai_order_details.originalPrice)

        $orderModel = WaiMaiOrderModel::query()
                                      ->where('createdAt', '>=', 1635696000)
                                      ->where('createdAt', '<=', 1639497600)
                                      ->where('sourceType', 3)
                                      ->where('orderStatus', '!=', WaiMaiDBEnum::ORDER_STATUS_7)
                                      ->orderBy('createdAt');

        $orderModel
            ->chunk(500, function ($orders) {

                $orderIds = $orders->pluck('orderId');
                $logs     = WaiMaiCallbackLogModel::query()
                                                  ->whereIn('orderId', $orderIds)
                                                  ->where(function ($query) {
                                                      $query->where('route',
                                                          '/api/pay/callback/elmWaiMai/push?type=10')
                                                            ->orWhere('route',
                                                                '/api/pay/callback/mtWaiMai/pushOrder');
                                                  })
                                                  ->get()
                                                  ->keyBy('orderId');


                $orders->each(function ($item) use ($logs) {

                    // 获取单行的镜像数据
                    $log = $logs[$item->orderId]['requestData'] ?? [];
                    if (!$log) {
                        $c = BaseWaiMai::getIns($item->sourceType, $item->shopId)
                                       ->getOrderDetail($item->orderId);
                        if (!$c['status'] || !$c['oriData']) {
                            $this->errs[] = $item->orderId . ' - null - ' . ((string)$c['msg']);
                            return;
                        }

                        $log = $c['oriData'];
                    } else {
                        $log = json_decode($log, true);
                    }

                    if ($item->sourceType == WaiMaiDBEnum::SOURCE_TYPE_MT_WM) {
                        $this->mt($item, $log);
                    } elseif ($item->sourceType == WaiMaiDBEnum::SOURCE_TYPE_ELM) {
                        $this->elm($item, $log);
                    }

                    echo $item->orderId . ' - success' . PHP_EOL;
                });
            });

        collect([
            ['orderId' => 108263161320662104, 'packingPrice' => 160],
            ['orderId' => 108263162521089199, 'packingPrice' => 220],
            ['orderId' => 130093952224627655, 'packingPrice' => 330],
            ['orderId' => 108263162699611169, 'packingPrice' => 100],
            ['orderId' => 108263163088929314, 'packingPrice' => 130],

        ])->each(function ($item) {
            $orderId      = $item['orderId'];
            $packingPrice = $item['packingPrice'];

            // 特殊没有镜像的订单手动处理
            $order                = WaiMaiOrderModel::query()->where('orderId', $orderId)->first();
            $order->packingPrice  = $packingPrice;
            $order->discountPrice = $order['originalPrice'] - $order['originalShippingPrice'] + $order->packingPrice - $order['expectIncome'];
            $order->otherPrice    = $order->discountPrice - $order['platformPrice'] - $order['activityExpenditure'];
            $order->save();

            $orderDetailData = $order->orderDetailsRel->map(function ($item) {
                $item->timestamps = false;
                unset($item['id']);
                return $item;
            })->toArray();

            $this->pushPacking($orderDetailData, $order->packingPrice);

            // 平台菜的优惠
            $this->shareDetailDiscount($orderDetailData, $order['discountPrice']);

            // 平摊所有菜品的收入
            $this->shareDetailIncomes($orderDetailData, $order['expectIncome']);

            WaiMaiOrderDetailModel::query()->where('orderId', $order->orderId)->delete();
            WaiMaiOrderDetailModel::query()->insert($orderDetailData);
        });

        if ($this->errs) {
            dump('------errs:------');
            dump($this->errs);
        } else {
            dump('------success:------');
        }

        // 3. 校验 waimai_orders.originalPrice - originalShippingPrice - packingPrice = sum(waimai_order_details.originalPrice)
        $orderModel
            ->chunk(500, function ($orders) {
                $orders->each(function ($order) {
                    $total  = $order->originalPrice - $order->originalShippingPrice - $order->packingPrice;
                    $detail = $order->orderDetailsRel->sum('originalPrice');
                    if ($total != $detail) {
                        dump($order->orderId . " - {$order->sourceType} - {$total} - {$detail}");
                    }
                });

            });
    }

    private function elm($order, array $log)
    {
        $log = json_decode($log['message'], true);

        DB::beginTransaction();

        // 饿了么：discountPrice, redPrice, redLists, activityExpenditure, otherPrice
        $ordersUpdate = [];

        // 优惠的配送费
        $discountShipping = abs($this->bcmul100($log['logisticsActivity']['amount'] ?? 0));

        $ordersUpdate['redPrice'] = $this->bcmul100(abs($log['activityTotal'] ?? 0)) + $discountShipping; // 配送费优惠要单独加
        $ordersUpdate['redLists'] = json_encode(collect($log['orderActivities'])
            ->add(['name' => '配送费优惠', 'amount' => bcdiv($discountShipping, 100, 2)])
//            ->where('categoryId', 15)
            ->map(function ($item) {
                if ($item['amount'] == 0) {
                    return null;
                }

                return [
                    'n' => $item['name'],
                    'p' => abs($this->bcmul100($item['amount'])),
                ];
            })->filter()->values()->toArray(), JSON_UNESCAPED_UNICODE);

        // 商家承担的支出金额
        $activityExpenditure = 0;

        // 1. 活动支出
        collect($log['orderActivities'] ?? [])->each(function ($item) use (&$activityExpenditure) {
            $activityExpenditure = bcadd($activityExpenditure, $item['restaurantPart'] ?? 0, 2);
        });
        $ordersUpdate['activityExpenditure'] = abs($this->bcmul100($activityExpenditure));

        // 2.配送费支出
        $ordersUpdate['activityExpenditure'] += abs($this->bcmul100($log['logisticsActivity']['restaurantPart'] ?? 0));

        // 优惠金额 = 菜品原价合计 + 包装费 - 营业收入
        $ordersUpdate['discountPrice'] = $order['originalPrice'] - $order['originalShippingPrice'] + $order['packingPrice'] - $order['expectIncome'];

        $ordersUpdate['otherPrice'] = $ordersUpdate['discountPrice'] - $order['platformPrice'] - $ordersUpdate['activityExpenditure'];


        WaiMaiOrderModel::query()->where('orderId', $order->orderId)->update($ordersUpdate);

        // waimai_order_details: +包装物-行，payPrice, discountPrice, incomes
        $orderDetailData = $order->orderDetailsRel->map(function ($item) {
            $item->timestamps = false;
            unset($item['id']);
            return $item;
        })->toArray();
        if (!$orderDetailData) {

            // 把菜篮子的菜品合并起来
            $detailArr = [];
            collect($log['groups'])->where('type', 'normal')
                                   ->each(function ($item) use (&$detailArr) {
                                       collect($item['items'])->each(function ($i) use (&$detailArr) {
                                           $detailArr[] = $i;
                                       });
                                   });

            foreach ($detailArr as $detail) {

                $productProperty = '';
                foreach ($detail['attributes'] ?? [] as $at) {
                    $productProperty .= $at['name'] . ":" . $at['value'] . ';';
                }

                $orderDetailData[] = [
                    'brandId'           => ShopService::getShopInfo($order->shopId)->brandId ?? 0,
                    'shopId'            => $order->shopId,
                    'orderId'           => $order->orderId,
                    'productName'       => $detail['name'] ?? '',
                    'productProperty'   => $productProperty,
                    'unit'              => '份',
                    'originalUnitPrice' => $originUnitPrice = $this->bcmul100($detail['price'] ?? 0),
                    'num'               => $num = $detail['quantity'] ?? 0,
                    'originalPrice'     => $originUnitPrice * $num,
                    'createdAt'         => $order->createdAt->timestamp,
                    'updatedAt'         => $order->updatedAt->timestamp,
                    'productType'       => WaiMaiOrderDetailModel::PRODUCT_TYPE_1,
                ];
            }
        }

        // 菜品明细加上包装物
        $this->pushPacking($orderDetailData, $order['packingPrice']);

        // 平台菜的优惠
        $this->shareDetailDiscount($orderDetailData, $ordersUpdate['discountPrice']);

        // 平摊所有菜品的收入
        $this->shareDetailIncomes($orderDetailData, $order['expectIncome']);

        WaiMaiOrderDetailModel::query()->where('orderId', $order->orderId)->delete();
        WaiMaiOrderDetailModel::query()->insert($orderDetailData);

        DB::commit();
    }

    private function mt($order, array $log)
    {
        $log = MtWaiMaiOrderService::getIns(WaiMaiDBEnum::SOURCE_TYPE_MT_WM)
                                   ->recDecode($log);

        DB::beginTransaction();

        $ordersUpdate = [];

        // waimai_orders：packingPrice,discountPrice,otherPrice
        $ordersUpdate['packingPrice'] = 0;
        foreach ($log['detail'] as $detail) {
            $ordersUpdate['packingPrice'] += ((float)bcmul($detail['box_price'], $detail['box_num'], 2));
        }
        $ordersUpdate['packingPrice'] = $this->bcmul100($ordersUpdate['packingPrice']);

        $ordersUpdate['discountPrice'] = $order['originalPrice'] - $order['originalShippingPrice'] + $ordersUpdate['packingPrice'] - $order['expectIncome'];
        $ordersUpdate['otherPrice']    = $ordersUpdate['discountPrice'] - $order['platformPrice'] - $order['activityExpenditure'];

        // 历史的垃圾数据
        $ordersUpdate['originalShippingPrice'] = $this->bcmul100($log['shipping_fee'] ?? 0);

        WaiMaiOrderModel::query()->where('orderId', $order->orderId)->update($ordersUpdate);

        // waimai_order_details: +包装物-行，payPrice, discountPrice, incomes
        $orderDetailData = $order->orderDetailsRel->map(function ($item) {
            $item->timestamps = false;
            unset($item['id']);
            return $item;
        })->toArray();

        // 菜品明细加上包装物
        $this->pushPacking($orderDetailData, $ordersUpdate['packingPrice']);

        // 平台菜的优惠
        $this->shareDetailDiscount($orderDetailData, $ordersUpdate['discountPrice']);

        // 平摊所有菜品的收入
        $this->shareDetailIncomes($orderDetailData, $order['expectIncome']);

        WaiMaiOrderDetailModel::query()->where('orderId', $order->orderId)->delete();
        WaiMaiOrderDetailModel::query()->insert($orderDetailData);

        DB::commit();
    }


    private function bcmul100($price): int
    {
        return (int)bcmul($price, 100);
    }

    /**
     * 菜品明细加上包装物
     * @param array $orderDetailData
     * @param int $packingPrice
     */
    protected function pushPacking(array &$orderDetailData, int $packingPrice)
    {
        $tem = $orderDetailData[0];

        $tem['productName']       = WaiMaiOrderDetailModel::PRODUCT_TYPE_2_TEXT;
        $tem['productType']       = WaiMaiOrderDetailModel::PRODUCT_TYPE_2;
        $tem['num']               = 1;
        $tem['originalUnitPrice'] = $tem['originalPrice'] = $packingPrice;
        $tem['productProperty']   = '';

        $orderDetailData[] = $tem;
    }

    /**
     * 平摊菜的优惠
     * @param array $orderDetailData
     * @param int $sumDiscountPrice
     */
    protected function shareDetailDiscount(array &$orderDetailData, int $sumDiscountPrice)
    {
        $lastDiscountPrice = $sumDiscountPrice;

        $sumOriginalPrice = (int)collect($orderDetailData)->sum('originalPrice');
        if (!$sumOriginalPrice) {
            return;
        }

        $orderDetailData = collect($orderDetailData)->sortBy('originalPrice')->values()->toArray();
        foreach ($orderDetailData as $k => $v) {
            if ($v['originalPrice'] == 0) {
                $orderDetailData[$k]['payPrice']      = 0;
                $orderDetailData[$k]['discountPrice'] = 0;
                continue;
            }

            if ($k == count($orderDetailData) - 1) {
                $discountPrice = $lastDiscountPrice;
            } else {
                $discountPrice = bcmul(bcdiv($v['originalPrice'], $sumOriginalPrice, 4), $sumDiscountPrice);
            }

            $orderDetailData[$k]['discountPrice'] = $discountPrice;
            $orderDetailData[$k]['payPrice']      = $v['originalPrice'] - $discountPrice;

            $lastDiscountPrice -= $discountPrice;
        }
    }

    /**
     * 平摊菜的收入
     * @param array $orderDetailData
     * @param int $expectIncome
     */
    protected function shareDetailIncomes(array &$orderDetailData, int $expectIncome)
    {
        $lastIncome = $expectIncome;

        $sumOriginalPrice = (int)collect($orderDetailData)->sum('originalPrice');
        if (!$sumOriginalPrice) {
            return;
        }

        $orderDetailData = collect($orderDetailData)->sortBy('originalPrice')->values()->toArray();

        foreach ($orderDetailData as $k => $v) {
            if ($v['originalPrice'] == 0) {
                $orderDetailData[$k]['incomes'] = 0;
                continue;
            }

            if ($k == count($orderDetailData) - 1) {
                $incomes = $lastIncome;
            } else {
                $incomes = bcmul(bcdiv($v['originalPrice'], $sumOriginalPrice, 4), $expectIncome);
            }

            $orderDetailData[$k]['incomes'] = $incomes;

            $lastIncome -= $incomes;
        }
    }
}
